package com.hsjk.szwj.module.pay.service;

import cn.hutool.json.JSONObject;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.hsjk.szwj.module.pay.controller.app.refund.vo.RefundOrderReqVO;
import com.hsjk.szwj.module.pay.dal.dataobject.config.ChannelRetMsg;
import com.hsjk.szwj.module.pay.dal.dataobject.config.MchAppConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxServiceWrapper;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxpayIsvsubMchParams;
import com.hsjk.szwj.module.pay.dal.dataobject.order.PayOrderDO;
import com.hsjk.szwj.module.pay.dal.dataobject.order.RefundOrderDO;
import com.hsjk.szwj.module.pay.enums.IfCodeEnum;
import com.hsjk.szwj.module.pay.enums.WxPayVersionEnum;
import com.hsjk.szwj.module.pay.util.WxpayKit;
import com.hsjk.szwj.module.pay.util.WxpayV3Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author chenjiawei
 * @desc 退款接口： 微信官方
 * @Date 2023/08/25 00:03
 **/
@Slf4j
@Service
public class WxpayRefundService extends AbstractRefundService {

    @Resource
    private PayInterfaceDefineService payInterfaceDefineService;

    @Override
    public String getIfCode() {
        return IfCodeEnum.WXPAY.getCode();
    }

    @Override
    public String preCheck(RefundOrderReqVO bizRQ, RefundOrderDO refundOrder, PayOrderDO payOrder) {
        return null;
    }

    @Override
    public ChannelRetMsg refund(RefundOrderReqVO bizRQ, RefundOrderDO refundOrder, PayOrderDO payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
        try {

            ChannelRetMsg channelRetMsg = new ChannelRetMsg();
            Long ifCodeId = payInterfaceDefineService.getIdByCode(getIfCode());
            WxServiceWrapper wxServiceWrapper
                    = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);
            //V2
            if (WxPayVersionEnum.WX_V2.getVersion().equals(wxServiceWrapper.getApiVersion())) {

                WxPayRefundRequest req = new WxPayRefundRequest();
                mchAppConfigContext.setIfCodeId(ifCodeId);
                //放置isv信息
                WxpayKit.putApiIsvInfo(mchAppConfigContext, req);
                // 商户订单号
                req.setOutTradeNo(String.valueOf(payOrder.getId()));
                // 退款单号
                req.setOutRefundNo(String.valueOf(refundOrder.getId()));
                // 订单总金额
                req.setTotalFee(payOrder.getAmount().intValue());
                // 退款金额
                req.setRefundFee(refundOrder.getRefundAmount().intValue());
                // 回调url
                req.setNotifyUrl(getNotifyUrl(refundOrder.getIfId()));
                WxPayService wxPayService = wxServiceWrapper.getWxPayService();

                WxPayRefundResult result = wxPayService.refundV2(req);
                // 退款发起成功,结果主动查询
                if ("SUCCESS".equals(result.getResultCode())) {
                    channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
                    channelRetMsg.setChannelOrderId(result.getRefundId());
                } else {
                    channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                    channelRetMsg.setChannelErrCode(result.getErrCode());
                    channelRetMsg.setChannelErrMsg(WxpayKit.appendErrMsg(result.getReturnMsg(), result.getErrCodeDes()));
                }
            } else if (WxPayVersionEnum.WX_V3.getVersion().equals(wxServiceWrapper.getApiVersion())) {
                //V3
                // 微信统一下单请求对象
                JSONObject reqJSON = new JSONObject();
                // 订单号
                reqJSON.putIfAbsent("out_trade_no", refundOrder.getPayOrderId());
                // 退款订单号
                reqJSON.putIfAbsent("out_refund_no", refundOrder.getId());
                // 回调地址
                reqJSON.putIfAbsent("notify_url", getNotifyUrl(refundOrder.getIfId()));

                JSONObject amountJson = new JSONObject();
                // 退款金额
                amountJson.putIfAbsent("refund", refundOrder.getRefundAmount());
                // 订单总金额
                amountJson.putIfAbsent("total", payOrder.getAmount());
                // 币种
                amountJson.putIfAbsent("currency", "CNY");
                reqJSON.putIfAbsent("amount", amountJson);
                // 特约商户
                if (mchAppConfigContext.isIsvsubMch()) {
                    WxpayIsvsubMchParams isvsubMchParams = (WxpayIsvsubMchParams)
                            configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchId()
                                    , mchAppConfigContext.getAppId(), ifCodeId);
                    reqJSON.putIfAbsent("sub_mchid", isvsubMchParams.getSubMchId());
                }

                JSONObject resultJSON = WxpayV3Util.refundV3(reqJSON, wxServiceWrapper.getWxPayService());
                String status = resultJSON.getStr("status");
                // 退款成功
                if ("SUCCESS".equals(status)) {
                    String refundId = resultJSON.getStr("refund_id");
                    channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
                    channelRetMsg.setChannelOrderId(refundId);
                } else if ("PROCESSING".equals(status)) {
                    // 退款处理中
                    String refundId = resultJSON.getStr("refund_id");
                    channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
                    channelRetMsg.setChannelOrderId(refundId);
                } else {
                    channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                    channelRetMsg.setChannelErrMsg(status);
                }

            }
            return channelRetMsg;
        } catch (WxPayException e) {
            log.error("微信退款WxPayException异常: ", e);
            ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
            WxpayKit.commonSetErrInfo(channelRetMsg, e);
            return channelRetMsg;

        } catch (Exception e) {
            log.error("微信退款Exception异常: ", e);
            return ChannelRetMsg.sysError(e.getMessage());
        }
    }

    @Override
    public ChannelRetMsg query(RefundOrderDO refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
        return null;
    }
}
